﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace HenIT.Controls
{
    public delegate string ListTextBoxFormatterDelegate(string inputString);
    public delegate void PrepareInputDelegate();
    public delegate void ParseOutputDelegate();

    public partial class ListTextBox : TextBox
    {
        private string enterValue = "";
        private int parsedItemCount = 0;
        public event PrepareInputDelegate PrepareInput;
        public event ParseOutputDelegate ParseOutput;
        public ListTextBoxFormatterDelegate ListTextBoxFormatter = null;

        #region Properties
        public bool AllEnabled { get; set; }
        public bool AllowDuplicates { get; set; } 
        #endregion

        public ListTextBox()
        {
            InitializeComponent();
        }

        #region Private methods
        private string FormatInput(string inputString, ListTextBoxFormatterDelegate customFormat)
        {
            string output = "";
            parsedItemCount = 0;
            inputString = inputString.Trim();
            if (inputString.Length > 0)
            {
                if (inputString.Trim('[', ']').Equals("all", StringComparison.CurrentCultureIgnoreCase))
                {
                    output = "[All]";
                    parsedItemCount = -1;
                }
                else
                {
                    //Split input string into array
                    List<string> inputs = (from s in inputString.Split(',', ';')
                                           where s.Trim().Length > 0
                                           select s).ToList<string>();

                    //Format each entry                    
                    List<string> formattedList = new List<string>();
                    foreach (string input in inputs)
                    {
                        string trimmedInput = input.Trim(' ');
                        string formatInput = "";
                        if (trimmedInput.Length > 0) //call custom code provided by caller
                            formatInput = customFormat(trimmedInput.Trim('[', ']'));

                        if (formatInput.Length > 0)
                        {
                            formattedList.Add("[" + formatInput.Trim('[', ']') + "]");
                            parsedItemCount++;
                        }
                        else
                            formattedList.Add(trimmedInput.Trim('[', ']'));
                    }

                    List<string> outputList;
                    if (AllowDuplicates)
                        outputList = (from s in formattedList
                                      orderby s
                                      select s).ToList<string>();
                    else
                    {
                        outputList = (from s in formattedList
                                      group s by s
                                          into s
                                          orderby s.Key
                                          select s.Key).ToList<string>();
                    }

                    StringBuilder sb = new StringBuilder();
                    foreach (string outputItem in outputList)
                    {
                        sb.Append(outputItem + ", ");
                    }

                    output = sb.ToString().TrimEnd(' ', ',');
                    if (parsedItemCount == 0 && output.Length == 0)
                    {
                        output = "[All]";
                        parsedItemCount = -1;
                    }
                }
            }
            else
            {
                output = "[All]";
                parsedItemCount = -1;
            }
            return output;
        } 
        #endregion

        #region Public methods
        public void SetText(List<string> list)
        {
            if (AllEnabled)
            {
                Text = "[All]";
            }
            else
            {
                StringBuilder sb = new StringBuilder();
                foreach (string item in list)
                {
                    sb.Append("[" + item + "], ");
                }
                Text = sb.ToString().Trim(',', ' ');
            }
        } 
        #endregion

        #region Override events
        protected override void OnKeyUp(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                bool stayAtEnd = false;
                stayAtEnd = (Text.Length == SelectionStart);
                DoValidation();
                if (stayAtEnd)
                    SelectionStart = Text.Length;
            }
            base.OnKeyUp(e);
        }
        private void DoValidation()
        {
            if (enterValue != Text && ListTextBoxFormatter != null)
            {
                RaisePrepareInput();

                Text = FormatInput(Text, ListTextBoxFormatter);
                AllEnabled = (Text == "[All]");
                if (parsedItemCount != 0)
                    RaiseParseInput();
            }
        }
        protected override void OnLeave(EventArgs e)
        {
            DoValidation();
            base.OnLeave(e);
            BackColor = SystemColors.Control;
        }
        protected override void OnEnter(EventArgs e)
        {
            enterValue = Text;
            BackColor = SystemColors.Window;
            base.OnEnter(e);
        } 
        #endregion

        #region Raise events
        private void RaiseParseInput()
        {
            if (ParseOutput != null)
                ParseOutput();

        }
        private void RaisePrepareInput()
        {
            if (PrepareInput != null)
                PrepareInput();
        } 
        #endregion
    }
}
